package compilers.condition;

import java.io.BufferedWriter;
import java.io.IOException;

import compilers.stmt.Condition;
import compilers.table.MemScope;
import compilers.types.Type;

public class Factor extends Term {
	Type fType;
	String fPre;
	Type fCast = null;
	Condition condition = null;
	
	public Type getCast() {
		return fCast;
	}
	
	public void setCast(Type type) {
		this.fCast = type;
	}
	
	public Type getBiggestType() {
		if(fCast != null) {
			return fCast;
		}
		return fType;
	}
	
	public Factor() {}
	
	public Factor(Condition condition, Type type) {
		this.fPre = "()";
		this.fType = type;
		this.condition = condition;
	}
	
	public Factor(Type fType, String fPre) {
		super();
		this.fType = fType;
		this.fPre = fPre;
	}
	
	public Factor(Type fType, Type fCast) {
		super();
		this.fType = fType;
		this.fCast = fCast;
	}

	public void print(int tab) {
		if(condition != null) {
			condition.print(tab);
			return;
		}
		for (int i=1;i<=tab;i++){System.out.print("\t");}System.out.print("|-");
		if (fPre == null) {
			System.out.println("Cast (" + fCast.getPType() + ")");
		} else {
			System.out.println("Factor (" + fPre + ")");
		}
		fType.print(tab+1);
	}

	@Override
	public void generate(BufferedWriter writer, MemScope scope) throws IOException {
		if (this.getfRes() == null) {
			System.out.println("throwing away useless code");
		} else if(condition == null){
			fType.setRes(this.getfRes());
			fType.generate(writer, scope);
			if(fCast != null) {
				return;
			}
			if (fPre.compareTo("!") == 0) {
				writer.write("conv " + this.getfRes().getPType() + " b\n");
				writer.write("not\n");
				writer.write("conv b " + this.getfRes().getPType() + "\n");
			} else if (fPre.compareTo("-") == 0) {
				writer.write("neg " + this.getfRes().getPType() + "\n");
			}
		} else {
			condition.generate(writer, scope);
		}
	}
	
	
	
	@Override
	public void setRes(Type fRes) {
		if(condition != null) {
			condition.setfRes(fRes);
		} else {
			super.setfRes(fRes);
		}
		
	}

	@Override
	public Type getfRes() {
		if(condition != null) {
			return condition.getfRes();
		}
		return super.getfRes();
	}

	@Override
	public void setfRes(Type fRes) {
		if(condition != null) {
			condition.setfRes(fRes);
		} else {
			super.setfRes(fRes);
		}
	}

	public Type compute() {
		if(condition != null) {
			return condition.compute();
		}
		
		if (fPre != null) {
			if ((fType != null) && (fType.isConstant())) {
				return fType.computeFactor(fPre);
			}
		}
		return null;
	}

}
